Skip to content

fishaudio: reuse streaming websocket and prebuffer initial chunks#2017

Merged
toubatbrian merged 3 commits into
mainfrom
pilaw-glared-elisions
Jul 15, 2026
Merged

fishaudio: reuse streaming websocket and prebuffer initial chunks#2017
toubatbrian merged 3 commits into
mainfrom
pilaw-glared-elisions

Conversation

@rosetta-livekit-bot

@rosetta-livekit-bot rosetta-livekit-bot Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Reconcile the Fish Audio streaming websocket port with the superseding Python and JavaScript behavior now on main.

Source diff coverage

This reconciles both Python sources and current JS main:

JavaScript adaptations:

  • Durations use milliseconds (300_000).
  • Node ws lifecycle and readyState checks replace aiohttp websocket behavior.
  • Shared ConnectionPool.withConnection handles checkout, return, abort, and failure removal.
  • A private module-local pool association avoids exposing ConnectionPool as public Fish Audio API.

TDD and verification

RED lifecycle tests initially reported 3 failures:

  • An in-flight s2-pro prewarm survived a change to s2.1-pro.
  • Failed-socket cleanup needed a separate subsequent-turn assertion matching the zero-retry stream contract.
  • Reusing a websocket that closed while idle timed out.

GREEN: plugins/fishaudio/src/tts.test.ts passes all 10 tests, covering sequential reuse, prewarming, completed and in-flight model invalidation, failure and close cleanup, idle closure, immediate first-frame emission, and final-frame handling.

Passed checks:

  • pnpm test -- --run plugins/fishaudio/src/tts.test.ts.
  • pnpm --filter @livekit/agents-plugin-fishaudio lint.
  • pnpm --filter @livekit/agents-plugin-fishaudio build.
  • pnpm build.
  • pnpm lint.
  • pnpm format:check.

The Fish Audio changeset is a patch release.

Cue voice E2E

  • Session: sid_f5a682549ea6.
  • Exact head: 19abcfd199b0cd58144aa8df5ec0fd130a951086.
  • Providers: credentialed LiveKit STT/LLM and credentialed Fish Audio TTS.
  • Boundary: temporary protocol-compatible local websocket forwarder counted upgrades, captured model headers, and timestamped provider frames; it was built before use and removed afterward.

Turn 1 waited for full playout with:

agent_state_changed(.new_state="AS_SPEAKING") -> agent_state_changed(.new_state="AS_LISTENING")[30s]

It resolved at session-relative 9513 ms. TTS TTFB was 156.669 ms. Prewarm opened upgrade #1 with model s2-pro; the first turn reused that same connection, with no second upgrade before synthesis.

Turn 2 changed the model and waited for the tool, speech, and full playout:

function_tools_executed(.function_calls[0].name="switchFishModel") -> agent_state_changed(.new_state="AS_SPEAKING")[15s] -> agent_state_changed(.new_state="AS_LISTENING")[30s]

It resolved at session-relative 24214 ms. TTS TTFB was 147.254 ms. Exactly upgrade #2 opened with model s2.1-pro, followed by successful speech and playout.

Immediate-frame evidence:

  • The deterministic test resolves stream.next() from the first complete provider audio event before a second provider event is sent.
  • On the credentialed turn, the first and second provider frames were 89.579 ms apart and agent speech began from the first frame before the second arrived.
  • Worker logs record playout completed without interruption for both turns.
  • Cue ended cleanly before artifacts were inspected; both per-turn WAVs contain nonzero agent-channel audio.

Persisted artifacts and SHA-256:

  • Full session WAV: ~/.cue-cli/sessions/sid_f5a682549ea6/recording.wav5745fdc5272427b8fae907fea11cf0e2e947ccd66bd364a82e6ea71fe1bc2215.
  • Turn 1 WAV: ~/.cue-cli/sessions/sid_f5a682549ea6/recordings/001_run/recording.wav8e52359e73dd2eb64fb942a85c544bc662f0c04601682ad45639f03c6b31bbd0.
  • Turn 2 WAV: ~/.cue-cli/sessions/sid_f5a682549ea6/recordings/002_run/recording.wav9bdc45a68f897955a1ffe7d6513e7877babd6c6f8aa409fb62702d1b44a14721.
  • Turn 1 result JSON: ~/.cue-cli/sessions/sid_f5a682549ea6/recordings/001_run/result.json5be009b38e7c6c91e2f1f02b8f11f6e943bdf2176536065b647af56144bbdb56.
  • Turn 2 result JSON: ~/.cue-cli/sessions/sid_f5a682549ea6/recordings/002_run/result.json3f98d27ae2985eb88394204fc7881481f97badbc36f7521bdaa9f30f5149de43.
  • Worker/proxy log: /tmp/task-2017-final-worker.log837b04c57b7a845bcb487cde918fc19de2fb8ae8f374cf846753f7aafd1e5ca0.

Boundary limitation: proxy timestamps are protocol-compatible provider receive/forward timestamps, not internal Fish server timestamps. SDK immediacy is established by the deterministic first-event test and corroborated by Cue TTFB and speech timing.

Review

Independent reconciliation reviews returned:

  • Spec compliance: APPROVED.
  • Code quality: APPROVED with no Critical/Important findings.

Ported from livekit/agents#6368 and reconciled with livekit/agents#6423 and #2033.

@rosetta-livekit-bot
rosetta-livekit-bot Bot requested a review from a team as a code owner July 10, 2026 06:40
@changeset-bot

changeset-bot Bot commented Jul 10, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 19abcfd

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 36 packages
Name Type
@livekit/agents-plugin-fishaudio Patch
@livekit/agents Patch
@livekit/agents-plugin-anam Patch
@livekit/agents-plugin-anthropic Patch
@livekit/agents-plugin-assemblyai Patch
@livekit/agents-plugin-baseten Patch
@livekit/agents-plugin-bey Patch
@livekit/agents-plugin-cartesia Patch
@livekit/agents-plugin-cerebras Patch
@livekit/agents-plugin-deepgram Patch
@livekit/agents-plugin-did Patch
@livekit/agents-plugin-elevenlabs Patch
@livekit/agents-plugin-google Patch
@livekit/agents-plugin-hedra Patch
@livekit/agents-plugin-hume Patch
@livekit/agents-plugin-inworld Patch
@livekit/agents-plugin-lemonslice Patch
@livekit/agents-plugin-liveavatar Patch
@livekit/agents-plugin-livekit Patch
@livekit/agents-plugin-minimax Patch
@livekit/agents-plugin-mistral Patch
@livekit/agents-plugin-mistralai Patch
@livekit/agents-plugin-neuphonic Patch
@livekit/agents-plugin-openai Patch
@livekit/agents-plugin-perplexity Patch
@livekit/agents-plugin-phonic Patch
@livekit/agents-plugin-resemble Patch
@livekit/agents-plugin-rime Patch
@livekit/agents-plugin-runway Patch
@livekit/agents-plugin-sarvam Patch
@livekit/agents-plugin-silero Patch
@livekit/agents-plugin-soniox Patch
@livekit/agents-plugin-tavus Patch
@livekit/agents-plugin-trugen Patch
@livekit/agents-plugin-xai Patch
@livekit/agents-plugins-test Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 1 additional finding.

Open in Devin Review

toubatbrian and others added 2 commits July 15, 2026 10:14
Preserve immediate first-frame delivery while reusing prewarmed websockets through the shared connection pool.

Co-authored-by: Cursor <cursoragent@cursor.com>
Reject stale prewarm connections and replace sockets that close while idle so model changes and subsequent turns remain correctly configured.

Co-authored-by: Cursor <cursoragent@cursor.com>

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 1 additional finding in Devin Review.

Open in Devin Review

Comment thread plugins/fishaudio/src/tts.ts
@toubatbrian
toubatbrian merged commit ccb51a4 into main Jul 15, 2026
8 checks passed
@toubatbrian
toubatbrian deleted the pilaw-glared-elisions branch July 15, 2026 20:49
@github-actions github-actions Bot mentioned this pull request Jul 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant